package cn.com.libertymutual.core.util;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.Closeable;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import ognl.NoSuchPropertyException;
import ognl.Ognl;
import ognl.OgnlException;

import org.hibernate.Hibernate;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.proxy.HibernateProxyHelper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.data.domain.Page;

public class Helper {
	/**
	 * 判断数组arr是否全部为空值
	 * 
	 * @param arr
	 * @return
	 */
	public static boolean isAllEmpty(Object[] arr) {
		if (arr == null || arr.length == 0) return true;
		for (Object o : arr) {
			if (!Helper.isEmpty(o)) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 判断字符串是否为空.如果str全为空白字符串,返回false
	 * 
	 * @param value
	 * @return
	 */
	public static boolean isEmpty(String value) {
		return value == null || value.trim().length() == 0;
	}

	/**
	 * 判断Object对象是否为空
	 * 
	 * @param value
	 * @return
	 */
	public static boolean isEmpty(Object value) {
		if (value == null) return true;
		if (value instanceof String || value instanceof CharSequence) return isEmpty(value.toString());
		if (value.getClass().isArray()) {
			return Array.getLength(value) == 0;
		}
		if (value instanceof Collection) {
			return ((Collection<?>) value).isEmpty();
		}
		if (value instanceof Map) {
			return ((Map<?, ?>) value).isEmpty();
		}
		if (value instanceof Iterable) {
			return !((Iterable<?>) value).iterator().hasNext();
		}
		if (value instanceof Iterator) {
			return !((Iterator<?>) value).hasNext();
		}
		return false;
	}

	/**
	 * 判断字符串str是否不为空.如果str全为空白字符串,返回false
	 * 
	 * @param str
	 * @return
	 * @see #isEmpty(String)
	 */
	public static boolean isNotEmpty(String str) {
		return !isEmpty(str);
	}

	/**
	 * 判断obj是否不为空
	 * 
	 * @param obj
	 * @return
	 * @see #isEmpty(Object)
	 */
	public static boolean isNotEmpty(Object obj) {
		return !isEmpty(obj);
	}

	/**
	 * 得到obj的长度
	 * 
	 * @param obj 数组/Collection/Map/Iterable
	 * @return obj的长度或者-1(obj不为数组/Collection/Map/Iterable)
	 */
	public static int getLength(Object obj) {
		if (obj == null) return 0;
		if (obj.getClass().isArray()) {
			return Array.getLength(obj);
		}

		if (obj instanceof Collection) {
			return ((Collection<?>) obj).size();
		}

		if (obj instanceof Map) {
			return ((Map<?, ?>) obj).size();
		}
		if (obj instanceof Iterable) {
			int length = 0;
			Iterator<?> it = ((Iterable<?>) obj).iterator();
			while (it.hasNext())
				length++;
			return length;
		}

		return -1;
	}

	/**
	 * 得到value中第index个数据
	 * 
	 * @param source 数组/List/Iterable/Iterator
	 * @param index 数组下标索引,从0开始
	 * @return
	 */
	public static Object getValue(Object source, int index) {
		if (isEmpty(source)) return null;
		try {
			if (source.getClass().isArray()) {
				// 数组
				return Array.get(source, index);
			}
			if (source instanceof List) {
				// List
				return ((List<?>) source).get(index);
			}
		} catch (ArrayIndexOutOfBoundsException e) {
			// 下标越界则返回null
			return null;
		}

		if (source instanceof Iterable) {
			// Iterable
			source = ((Iterable<?>) source).iterator();
		}
		if (source instanceof Iterator) {
			// Iterator
			Iterator<?> it = (Iterator<?>) source;
			while (it.hasNext()) {
				if (index == 0) return it.next();
				index--;
			}
		}

		return null;
	}

	/**
	 * 得到source对象的name属性的值
	 * 
	 * @param source
	 * @param name
	 * @return
	 */
	public static Object getValue(Object source, String name) {
		if (source == null) return null;
		PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(source.getClass(), name);
		if (pd == null) return null;
		Method readMethod = pd.getReadMethod();
		if (readMethod == null) return null;
		if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
			readMethod.setAccessible(true);
		}

		try {
			return readMethod.invoke(source);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return null;
	}

	/**
	 * 得到source对象pd属性点值
	 * 
	 * @param source
	 * @param pd
	 * @return
	 */
	public static Object getValue(Object source, PropertyDescriptor pd) {
		if (source == null) return null;
		Method readMethod = pd.getReadMethod();
		if (readMethod == null) return null;
		if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
			readMethod.setAccessible(true);
		}
		try {
			return readMethod.invoke(source);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return null;
	}

	/**
	 * 对source的pd属性进行赋值
	 * 
	 * @param source
	 * @param pd
	 * @param value
	 */
	public static void setValue(Object source, PropertyDescriptor pd, Object value) {
		if (source == null) return;
		Method writeMethod = pd.getWriteMethod();
		if (writeMethod == null) {
			setValue(source, pd.getName(), value);
			return;
		}
		if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
			writeMethod.setAccessible(true);
		}
		try {
			writeMethod.invoke(source, value);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 设置source的name属性的值为value
	 * 
	 * @param source
	 * @param name
	 * @param value
	 */
	public static void setValue(Object source, String name, Object value) {
		try {
			Ognl.setValue(name, source, value);
		} catch (NoSuchPropertyException ignore) {
			// TODO 没有的属性则忽略
		} catch (OgnlException e) {
			// TODO Auto-generated catch block
			// e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	/**
	 * 设置obj对象的多个值,数据从value中读取
	 * 
	 * @param obj
	 * @param json Map/POJO对象,应该是一个{}类型的JSON数据
	 * @return obj
	 * @throws CustomException
	 */
	public static <T> T setValue(T obj, Object value) {
		if (obj == null) return obj;
		if (value == null) return obj;
		// if (value instanceof String) return setValue(obj, StringHelper.toJson((String) value));
		if (value instanceof Map) {
			Map<?, ?> map = (Map<?, ?>) value;
			for (Object key : map.keySet()) {
				setValue(obj, StringUtil.trim(key), map.get(key));
			}
		} else {
			Helper.copyValues(value, obj);
		}
		return obj;
	}

	/**
	 * 转换o的类型
	 * 
	 * @param cls
	 * @param obj
	 * @return
	 */
	public static Object cast(Class<?> cls, Object obj) {
		if (obj == null) {
			return null;
		}
		if (cls == null) {
			return obj;
		}
		Class<?> objCls = obj.getClass();

		if (cls == obj.getClass() || cls.isAssignableFrom(objCls)
				|| (cls.isArray() && objCls.isArray() && cls.getComponentType() == objCls.getComponentType())) {
			// obj是cls的子类
			return obj;
		}

		if (cls == Byte.TYPE || cls == Byte.class) {
			return (byte) NumberHelper.intValue(obj);
		} else if (cls == Character.TYPE || cls == Character.class) {
			// 单字节,obj必须是数字或者String
			if (obj instanceof CharSequence) {
				if (((CharSequence) obj).length() < 1) {
					return (char) 0;
				}
				return ((CharSequence) obj).charAt(0);
			}
			return ((char) NumberHelper.intValue(obj));
		} else if (cls == Short.TYPE || cls == Short.class) {
			return ((short) NumberHelper.intValue(obj));
		} else if (cls == Integer.TYPE || cls == Integer.class) {
			return (NumberHelper.intValue(obj));
		} else if (cls == Long.TYPE || cls == Long.class) {
			return (NumberHelper.longValue(obj));
		} else if (cls == Float.TYPE || cls == Float.class) {
			return (NumberHelper.floatValue(obj));
		} else if (cls == Double.TYPE || cls == Double.class) {
			return (NumberHelper.doubleValue(obj));
		} else if (cls == Boolean.class || cls == Boolean.TYPE) {
			return StringUtil.parseBoolean(obj);
		} else if (cls == String.class) {
			return ((obj == null) ? null : StringUtil.trim(obj));
		} else if (cls == Date.class) {
			try {
				obj = DateUtil.convertStringToDate(obj.toString());
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				obj=null;
			}
			return obj;
		} else if (cls.isArray() && objCls.isArray() && cls.getComponentType() != objCls.getComponentType()) {
			int l = Array.getLength(obj);
			Class<?> clazz = cls.getComponentType();
			Object array = Array.newInstance(cls.getComponentType(), l);
			for (int i = 0; i < l; i++) {
				if (!clazz.isPrimitive()) {
					Array.set(array, i, cast(cls.getComponentType(), Array.get(obj, i)));
				} else if (clazz == Double.TYPE) {
					Array.setDouble(array, i, NumberHelper.doubleValue(Array.get(obj, i)));
				} else if (clazz == Float.TYPE) {
					Array.setFloat(array, i, NumberHelper.floatValue(Array.get(obj, i)));
				} else if (clazz == Long.TYPE) {
					Array.setLong(array, i, NumberHelper.longValue(Array.get(obj, i)));
				} else if (clazz == Integer.TYPE) {
					Array.setInt(array, i, NumberHelper.intValue(Array.get(obj, i)));
				} else if (clazz == Short.TYPE) {
					Array.setShort(array, i, (short) NumberHelper.intValue(Array.get(obj, i)));
				} else if (clazz == Byte.TYPE) {
					Array.setByte(array, i, (byte) NumberHelper.intValue(Array.get(obj, i)));
				} else if (clazz == Character.TYPE) {
					Array.setChar(array, i, (Character) cast(clazz, Array.get(obj, i)));
				} else if (clazz == Boolean.TYPE) {
					Array.setBoolean(array, i, (Boolean) cast(clazz, Array.get(obj, i)));
				}
			}
			obj = array;
		} else if (cls.isArray() && !objCls.isArray()) {
			Class<?> clazz = cls.getComponentType();
			Object[] array = (Object[]) Array.newInstance(clazz, 1);
			array[0] = cast(clazz, obj);
			obj = array;
		}
		return obj;
	}

	/*--- Java Bean 相关方法 ---*/

	/**
	 * 复制一个对象source
	 * 
	 * @param source 要复制的对象
	 * @param ignoreProperties 不需要复制的属性
	 * @return
	 * @throws BeansException
	 */
	@SuppressWarnings("unchecked")
	public static <T> T copy(T source, String... ignoreProperties) throws BeansException {
		return (T) copyTo(source, (T) BeanUtils.instantiate(Hibernate.getClass(source)), ignoreProperties);
	}

	// /**
	// *
	// * 将source的属性复制到target中, 向target赋值时,会调用setter方法
	// *
	// * @param source
	// * @param target
	// * @return target
	// * @throws BeansException
	// * @see {@link BeanUtils#copyProperties(Object, Object)}
	// */
	// public static <T> T copy(Object source, T target) throws BeansException {
	// BeanUtils.copyProperties(source, target);
	// return target;
	// }

	/**
	 * 
	 * 将source的属性复制到target中, 向target赋值时,会调用setter方法
	 * 
	 * @param source
	 * @param target
	 * @param ignoreProperties 不copy的属性
	 * @return target
	 * @throws BeansException
	 * @see {@link BeanUtils#copyProperties(Object, Object, String[])}
	 */
	public static <T> T copyTo(Object source, T target, String... ignoreProperties) throws BeansException {
		if (source == null) return null;
		BeanUtils.copyProperties(source, target, ignoreProperties);
		return target;
	}

	/** 基础数据类型的class */
	static final Class<?>[] BASIC_CLASSES = new Class<?>[] { Number.class, Boolean.class, String.class, Date.class,
			CharSequence.class, Character.class };

	/**
	 * 判断clazz是否为基础数据类型,是否为Boolean/Number/String/Date等基础数据类型
	 * 
	 * @param clazz
	 * @return
	 */
	public static boolean isBasicClass(Class<?> clazz) {
		if (clazz.isPrimitive()) return true;
		if (clazz.isArray()) return isBasicClass(clazz.getComponentType());
		for (Class<?> cls : BASIC_CLASSES) {
			if (cls.isAssignableFrom(clazz)) return true;
		}

		// String packageName = clazz.getPackage().getName();
		// if (packageName.startsWith("java.") || packageName.startsWith("javax.")) {
		// return true;
		// }
		for (Class<?> cls : BASIC_CLASSES) {
			if (cls.isAssignableFrom(clazz)) return true;
		}
		return false;
	}

	/**
	 * *
	 * 只复制基础数据类型的字段
	 *
	 * @param source
	 * @param target
	 * @return
	 * @throws BeansException
	 */
	public static <T> T copyBasicProperties(Object source, T target) throws BeansException {
		return Helper.copyBasicProperties(source, target, false, null);
	}

	

	/**
	 *
	 * 只复制基础数据类型的字段
	 * 
	 * @param source
	 * @param ignoreProperties 不需要处理的字段
	 * @return
	 * @throws BeansException
	 */
	@SuppressWarnings("unchecked")
	public static <T> T copyBasicProperties(T source, String... ignoreProperties) throws BeansException {
		if (source == null) return null;
		return Helper.copyBasicProperties(source, (T) BeanUtils.instantiate(Hibernate.getClass(source)), false,
				ignoreProperties);
	}

	/**
	 *
	 * 只复制基础数据类型的字段
	 * 
	 * @param source
	 * @param target
	 * @param ignoreProperties 不需要处理的字段
	 * @return T
	 * @throws BeansException
	 */
	public static <T> T copyToBasicProperties(Object source, T target, String... ignoreProperties)
			throws BeansException {
		return Helper.copyBasicProperties(source, target, false, ignoreProperties);
	}

	/**
	 * 只复制基础数据类型的字段
	 * 
	 * @param source
	 * @param target
	 * @param copyNull 是否复制null值
	 * @param ignoreProperties 不需要复制的字段
	 * @return target
	 * @throws BeansException
	 */
	public static <T> T copyBasicProperties(Object source, T target, boolean copyNull, String[] ignoreProperties)
			throws BeansException {
		if (source == null || target == null) return target;
		// Assert.notNull(source, "Source must not be null");
		// Assert.notNull(target, "Target must not be null");

		Class<?> actualEditable = target.getClass();
		PropertyDescriptor[] targetPds = BeanUtils.getPropertyDescriptors(actualEditable);
		List<String> ignoreList = (ignoreProperties != null) ? Arrays.asList(ignoreProperties) : null;

		Class<?> type;
		Method readMethod;
		Method writeMethod;
		Object value;
		PropertyDescriptor sourcePd;
		for (PropertyDescriptor targetPd : targetPds) {
			writeMethod = targetPd.getWriteMethod();
			if (writeMethod == null) continue;
			if (ignoreProperties == null || ignoreList.contains(targetPd.getName())) continue;
			type = targetPd.getPropertyType();
			if (!isBasicClass(type)) continue; // 不是基本数据类型

			sourcePd = BeanUtils.getPropertyDescriptor(source.getClass(), targetPd.getName());
			if (sourcePd == null) continue;

			readMethod = sourcePd.getReadMethod();
			if (readMethod == null) continue;

			try {

				if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
					readMethod.setAccessible(true);
				}
				value = readMethod.invoke(source);

				if (value == null && !copyNull) continue; // 如果得到的值为null且copyNull为false,则不复制

				if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
					writeMethod.setAccessible(true);
				}

				writeMethod.invoke(target, value);
			} catch (Throwable ex) {
				ex.printStackTrace();
				throw new FatalBeanException("Could not copy properties from source to target", ex);
			}
		}

		return target;
	}

	/**
	 * 
	 * 将source的不为null的属性copy到target中.向target赋值时,会调用setter方法
	 * 
	 * @param source
	 * @param target
	 * @return target
	 * @throws BeansException
	 */
	public static <T> T copyValues(Object source, T target) throws BeansException {
		return copyValues(source, target, null);
	}

	/**
	 * 将source的不为null的属性复制到target中 向target赋值时,会调用setter方法
	 * 
	 * @param source
	 * @param target
	 * @param ignoreProperties
	 * @return target
	 * @throws BeansException
	 * @see {@link BeanUtils#copyProperties(Object, Object, String[])}
	 */
	public static <T> T copyValues(Object source, T target, String[] ignoreProperties) throws BeansException {

		if (source == null || target == null) return target;
		// Assert.notNull(source, "Source must not be null");
		// Assert.notNull(target, "Target must not be null");

		Class<?> actualEditable = target.getClass();

		PropertyDescriptor[] targetPds = BeanUtils.getPropertyDescriptors(actualEditable);
		List<String> ignoreList = (ignoreProperties != null) ? Arrays.asList(ignoreProperties) : null;

		for (PropertyDescriptor targetPd : targetPds) {
			if (targetPd.getWriteMethod() != null
					&& (ignoreProperties == null || (!ignoreList.contains(targetPd.getName())))) {
				PropertyDescriptor sourcePd = BeanUtils.getPropertyDescriptor(source.getClass(), targetPd.getName());
				if (sourcePd != null && sourcePd.getReadMethod() != null) {
					try {
						Method readMethod = sourcePd.getReadMethod();
						if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
							readMethod.setAccessible(true);
						}
						Object value = readMethod.invoke(source);
						if (value == null) continue; // 如果得到的值为null则不复制
						Method writeMethod = targetPd.getWriteMethod();
						if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
							writeMethod.setAccessible(true);
						}
						writeMethod.invoke(target, value);
					} catch (Throwable ex) {
						throw new FatalBeanException("Could not copy properties from source to target", ex);
					}
				}
			}
		}
		return target;
	}

	/**
	 * 得到cls的所有属性描述
	 * 
	 * @param cls
	 * @return
	 */
	public static PropertyDescriptor[] getPropertyDescriptors(Class<?> cls) {
		return BeanUtils.getPropertyDescriptors(cls);
	}

	/**
	 * 得到cls的属性,得到父类定义的属性时,遍历到stopCls为止.
	 * 
	 * @param cls
	 * @param stopCls 所有在stopCls定以的对象不包含在返回字段中
	 * @return
	 * @throws CustomException
	 */
	public static PropertyDescriptor[] getPropertyDescriptors(Class<?> cls, Class<?> stopCls) {
		try {
			return Introspector.getBeanInfo(cls, stopCls).getPropertyDescriptors();
		} catch (IntrospectionException e) {
			// TODO Auto-generated catch block
			// e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

	/**
	 * 得到cls的propertyName属性
	 * 
	 * @param cls
	 * @param propertyName
	 * @return
	 */
	public static PropertyDescriptor getPropertyDescriptor(Class<?> cls, String propertyName) {
		return BeanUtils.getPropertyDescriptor(cls, propertyName);
	}

	/**
	 * 读取cls中属性propertyName的注解annotationClass
	 * 
	 * @param cls
	 * @param propertyName
	 * @param annotationClass
	 * @return
	 */
	public static <T extends Annotation> T getAnnotation(Class<?> cls, String propertyName, Class<T> annotationClass) {
		PropertyDescriptor pd = Helper.getPropertyDescriptor(cls, propertyName);
		if (pd == null) return null;
		/* 首先从getter方法中读取注解 */
		Method method = pd.getReadMethod();
		T annotation = method == null ? null : method.getAnnotation(annotationClass);
		if (annotation == null) {
			// 从setter方法读取注解
			method = pd.getWriteMethod();
			annotation = method == null ? null : method.getAnnotation(annotationClass);
		}
		if (annotation == null) {
			// 从Field中读取注解
			try {
				Field field = cls.getDeclaredField(propertyName);
				if (field != null) annotation = field.getAnnotation(annotationClass);
			} catch (NoSuchFieldException | SecurityException e) {
				e.printStackTrace();
			}
		}
		return annotation;
	}

	// /**
	// * 得到cls下所有字段的属性名,得到的这些字段必然有getter/setter方法
	// *
	// * @param cls
	// * @return
	// */
	// public static String[] getPropertyNames(Class<?> cls) {
	// PropertyDescriptor[] pds = Helper.getPropertyDescriptors(cls);
	// List<String> names = new ArrayList<String>();
	// for (PropertyDescriptor pd : pds) {
	// if (pd.getReadMethod() == null || pd.getWriteMethod() == null) continue;
	// names.add(pd.getName());
	// }
	// return names.toArray(new String[names.size()]);
	// }

	/**
	 * 得到cls下的除excludes外的所有字段名,得到的这些字段必然有getter/setter方法
	 * 
	 * @param cls
	 * @param excludes 不需要的字段
	 * @return
	 */
	public static String[] getPropertyNames(Class<?> cls, String... excludes) {
		// if (excludes == null || excludes.length == 0) return getPropertyNames(cls);
		List<String> a = excludes == null ? null : Arrays.asList(excludes);
		PropertyDescriptor[] pds = Helper.getPropertyDescriptors(cls);
		List<String> names = new ArrayList<String>();
		for (PropertyDescriptor pd : pds) {
			if (pd.getReadMethod() == null || pd.getWriteMethod() == null) continue;
			if (a != null && a.contains(pd.getName())) continue;
			names.add(pd.getName());
		}
		return names.toArray(new String[names.size()]);
	}

	/*--- Java Bean 相关方法 End ---*/

	/*--- Stream.close ---*/
	/**
	 * 执行Closeable对象的close方法
	 * 
	 * @param obj
	 */
	public static void close(Closeable obj) {
		if (obj == null) return;
		try {
			obj.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 关闭对象,调用obj.close()方法
	 * 
	 * @param obj
	 */
	public static void close(Object obj) {
		if (obj == null) return;
		try {
			Method method = obj.getClass().getDeclaredMethod("close");
			if (!Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
				method.setAccessible(true);
			}
			method.invoke(obj);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/*--- Stream.close End ---*/

	/*--- 数组集合相关方法 ---*/
	/**
	 * 将数组o的每个值分别加到集合中
	 * 
	 * @param c
	 * @param values 数组或列表等
	 * @return
	 */

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static int add(Collection c, Object values) {
		if (Helper.isEmpty(values)) return 0;
		int count = Helper.getLength(values);
		int result = 0;
		for (int i = 0; i < count; i++) {
			if (c.add(Helper.getValue(values, i))) result++;
		}
		return result;
	}

	/**
	 * 
	 * 将数组o的每个值分别加到集合中
	 * 
	 * @param c 集合对象
	 * @param values 数组
	 * @return 增加的数据个数
	 */
	public static <V> int add(Collection<V> c, V[] values) {
		if (Helper.isEmpty(values)) return 0;
		int count = 0;
		for (V value : values) {
			if (c.add(value)) count++;
		}
		return count;
	}

	/**
	 * 将迭代对象中的数据全部增加到集合中
	 * 
	 * @param c
	 * @param iterator
	 * @return
	 */
	public static <V> int add(Collection<V> c, Iterator<V> iterator) {
		if (iterator == null) return 0;

		int count = 0;
		while (iterator.hasNext()) {
			if (c.add(iterator.next())) count++;
		}
		return count;
	}

	/**
	 * 
	 * @param c
	 * @param iterable
	 * @return
	 * @see #add(Collection, Iterator)
	 */
	public static <V> int add(Collection<V> c, Iterable<V> iterable) {
		if (iterable == null) return 0;
		return add(c, iterable.iterator());
	}

	/*--- 数组集合相关方法 End ---*/

	/**
	 * 解析URL字符串
	 * 
	 * @param url URL字符串,可能是有%XX编码的字符串
	 * @return
	 */
	@SuppressWarnings("deprecation")
	public static String decodeURL(String url) {
		try {
			return URLDecoder.decode(url, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			return URLDecoder.decode(url);
		}
	}

	/**
	 * 将JavaBean转换为Map对象,JavaBean下的所有字段应是普通java对象
	 * 
	 * @param bean 要转换的JavaBean
	 * @param excludeProperties 排除的属性
	 * @param includeProperties 包含的属性
	 * @return
	 */
	public static Map<String, Object> toMap(Object bean, String[] excludeProperties, String[] includeProperties) {
		if (bean == null) return null;
		Map<String, Object> map = new LinkedHashMap<String, Object>();

		PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(bean.getClass());
		List<String> ignoreList = (excludeProperties != null) ? Arrays.asList(excludeProperties) : null;
		List<String> includeList = (includeProperties != null) ? Arrays.asList(includeProperties) : null;
		String name;
		Object value;
		for (PropertyDescriptor pd : pds) {
			name = pd.getName();
			if ("class".equals(name) || "declaringClass".equals(name) || "hibernateLazyInitializer".equals(name)
					|| "handler".equals(name))
				continue;
			if (includeList != null && !includeList.isEmpty() && !includeList.contains(name)) continue; // 指定要包含的属性
			if (ignoreList != null && ignoreList.contains(name)) continue; // 排除的属性
			value = getValue(bean, pd);
			if (value == null) continue;
			map.put(name, value);
		}
		return map;
	}

	/**
	 * 
	 * 将JavaBean转换为Map对象,JavaBean下的所有字段应是普通java对象
	 * 
	 * @param bean 要转换的JavaBean
	 * @param excludeProperties 排除的属性
	 * @return
	 */
	public static Map<String, Object> toMap(Object bean, String[] excludeProperties) {
		return Helper.toMap(bean, excludeProperties, null);
	}

	/**
	 * 将JavaBean转换为Map对象,JavaBean下的所有字段应是普通java对象
	 * 
	 * @param bean 要转换的JavaBean
	 * @return
	 */
	public static Map<String, Object> toMap(Object bean) {
		return Helper.toMap(bean, null, null);
	}

	/**
	 * 
	 * @Description: 把一个map对象的数据拷贝到一个type对象中去。
	 *
	 * @param type
	 * @param map
	 * @return 新建的type对象
	 *
	 * @date 2016年5月25日下午9:25:48
	 * @author hehaibo
	 */
	public static <T> T toObject(Map<?, ?> map, Class<T> type) {
		return (T) Helper.setValue(Helper.instantiate(type), map);
		// Object obj = null;
		// try {
		// // 创建 JavaBean 对象
		// obj = type.newInstance();
		// } catch (Exception e) {
		//
		// e.printStackTrace();
		// return null;
		// }
		//
		// // 获取对象的属性描述对象
		// PropertyDescriptor[] propertyDescriptors = BeanUtils.getPropertyDescriptors(type);
		// for (PropertyDescriptor descriptor : propertyDescriptors) {
		// String propertyName = descriptor.getName();
		//
		// if (map.containsKey(propertyName)) {
		// // 下面一句可以 try 起来，这样当一个属性赋值失败的时候就不会影响其他属性赋值。
		// Object value = map.get(propertyName);
		// setValue(obj, descriptor, value);
		// }
		// }
		// return (T) obj;
	}

	/**
	 * 将普通数组对象转换为Object[]
	 * 
	 * @param obj 普通数组对象,如int[]
	 * @return Object[]
	 */
	public static Object[] toArray(Object obj) {
		if (obj instanceof Object[]) return (Object[]) obj;
		int length = Helper.getLength(obj);
		Object[] arr = new Object[length];
		for (int i = 0; i < length; i++) {
			arr[i] = Helper.getValue(obj, i);
		}
		return arr;
	}

	

	/**
	 * 得到一个新建的clazz对象
	 * 
	 * @param clazz
	 * @return
	 */
	public static <T> T instantiate(Class<T> clazz) {
		return BeanUtils.instantiateClass(clazz);
	}

	/**
	 * 初始化Hibernta的延迟加载对象,同时会自动初始化entity下直接子属性和Set类属性.
	 * 注意,此方法在初始化entity的属性时,仅初始直接定义在entity中的属性,不再迭代属性下的属性
	 * 
	 * @param entity
	 * @return
	 */
	public static <T> T initialize(T entity) {
		return Helper.initialize(entity, 1, true);
	}

	/**
	 * 初始化entity,默认还会加载entity下的直接子对象
	 * 
	 * @param entity 实体类
	 * @param maxDepth >=0,迭代深度,一般情况下为1即可,仅处理entity的属性.为0则相当于不初始化entity下的任何lazy对象
	 * @return
	 */
	public static <T> T initialize(T entity, int maxDepth) {
		return Helper.initialize(entity, maxDepth, false);
	}

	/**
	 * 初始化entity,默认还会加载entity下的直接子对象
	 * 
	 * @param entity 实体类
	 * @param collection 是否初始化entity下的PersistentCollection对象
	 * @return
	 */
	public static <T> T initialize(T entity, boolean collection) {
		return Helper.initialize(entity, 1, collection);
	}

	/**
	 * 初始化entity,指定最大迭代hibernate对象的深度
	 * 
	 * @param entity 实体类
	 * @param maxDepth >=0,迭代深度,一般情况下为1即可,仅处理entity的属性.为0则相当于不初始化entity下的任何lazy对象
	 * @param collection 是否初始化entity下的PersistentCollection对象
	 * @return
	 */
	public static <T> T initialize(T entity, int maxDepth, boolean collection) {
		return Helper.initialize(entity, 0, maxDepth, collection);
	}

	/**
	 * 内部调用方法
	 * 
	 * @param entity 如果entity为数组类型，则相对与对其中的每个对象进行迭代
	 * @param depth 当前迭代深度,从0开始
	 * @param maxDepth 最大迭代深度,为0则相当于不初始化entity下的任何lazy对象
	 * @return
	 */
	static <T> T initialize(T entity, int depth, int maxDepth, boolean collection) {
		if (entity == null) return null;
		Hibernate.initialize(entity);
		if (depth >= maxDepth) return entity;
		if (entity instanceof Collection) {
			if (collection) {
				Iterator<?> it = ((Collection<?>) entity).iterator();
				while (it.hasNext()) {
					Helper.initialize(it.next(), depth, maxDepth, collection);
				}
			}
			return entity; // set子字段不迭代
		}

		if (entity instanceof Page) {
			// 分页对象对其content的内容进行初始化
			Helper.initialize(((Page<?>) entity).getContent(), depth, maxDepth, collection);
			return entity;
		}
		PropertyDescriptor[] pds = Helper
				.getPropertyDescriptors(HibernateProxyHelper.getClassWithoutInitializingProxy(entity));
		for (PropertyDescriptor pd : pds) {
			Object value = Helper.getValue(entity, pd);
			if (Hibernate.isInitialized(value)) { // 此属性已经初始化
				continue;
			}
			if (entity instanceof PersistentCollection && !collection) {
				// 不处理entity下的collection属性
				continue;
			}
			initialize(value, depth + 1, maxDepth, collection);
		}
		return entity;
	}

}
